#include <Windows.h>
#include "implementactivex.h"
#include <QString>
#include <QStringList>
#include <QSettings>
#include <QFileInfo>
#include "activexview.h"
#include <QPluginLoader>
#include <QMessageBox>
#include <QTextCodec>
#include "utility.h"
#include "datamanager.h"
#include "datatypedefine.h"
#include "objectentitesarray.h"
#include "positionarray.h"
#include "doublearray.h"
#include "writelogmanager.h"

typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
LPFN_ISWOW64PROCESS fnIsWow64Process; 
BOOL IsWow64() 
{ 
	BOOL bIsWow64 = FALSE; 
	fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress( 
		GetModuleHandle(TEXT("kernel32")),"IsWow64Process"); 
	if (NULL != fnIsWow64Process) 
	{ 
		if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64)) 
		{ 
			//log
		} 
	}
	return bIsWow64; 
}

ImplementActivex::ImplementActivex():_applicationDir(""),_plugin(NULL)
{
	_activexView = new ActivexView();
	_commonShapeParameter._setting = false;
	_currentScanMode = 0;
	//default property windows parameter
	_propertyWindowParameter._nameTextColor = osg::Vec3(0.0f,0.0f,0.0f);
	_propertyWindowParameter._nameTextSize = 15;
	_propertyWindowParameter._nameWidth = 0.30;
	_propertyWindowParameter._valueTextColor = osg::Vec3(0.0f,0.0f,0.0f);
	_propertyWindowParameter._valueTextSize = 12;
	_propertyWindowParameter._valueWidth = 0.70;
	_propertyWindowParameter._windowsWidth = 380;
	_propertyWindowParameter._windowsHeight = 280;
	_propertyWindowParameter._setting = false;
}

ImplementActivex::~ImplementActivex()
{
	delete _activexView;
	_activexView = NULL;
}

QWidget* ImplementActivex::getGLWidget()
{
	return _activexView->getGLWidget();
}

QObject* ImplementActivex::getActivexView()
{
	return _activexView;
}

void ImplementActivex::setQtPluginObject()
{
	bool is64 = IsWow64();
	QString setupfile = "";
	QVariant defvalue;
	defvalue.setValue<QString>("none");
	if(is64)
	{
		QSettings settings("HKEY_LOCAL_MACHINE\\Software\\Wow6432Node\\Classes\\CLSID\\{2AC26F09-1A4A-465B-A582-76C6268A8055}\\InProcServer32"
			,QSettings::NativeFormat);
		setupfile = settings.value("Default",defvalue).toString();
		if(setupfile =="none")
		{
			QSettings usersettings("HKEY_CURRENT_USER/",QSettings::NativeFormat);
			//QSettings usersettings("HKEY_USERS\\S-1-5-21-2237489092-261581234-1864942773-1000\\Software\\Classes\\Wow6432Node\\CLSID\\{2AC26F09-1A4A-465B-A582-76C6268A8055}\\InProcServer32"
			//,QSettings::NativeFormat);
			setupfile = settings.value("Software/Classes/Wow6432Node/CLSID/2AC26F09-1A4A-465B-A582-76C6268A8055/InProcServer32/Default",defvalue).toString();
		}
	}
	else
	{
		QSettings settings("HKEY_LOCAL_MACHINE\\Software\\Classes\\CLSID\\{2AC26F09-1A4A-465B-A582-76C6268A8055}\\InProcServer32"
			,QSettings::NativeFormat);
		setupfile = settings.value("Default",defvalue).toString();
		if(setupfile =="none")
		{
			QSettings usersettings("HKEY_CURRENT_USER\\Software\\Classes\\CLSID\\{2AC26F09-1A4A-465B-A582-76C6268A8055}\\InProcServer32"
			,QSettings::NativeFormat);
			setupfile = settings.value("Default",defvalue).toString();
		}
	}
	if(setupfile =="none")
	{
		//log
		return;
	}
	QFileInfo fileinfo(setupfile);
	_applicationDir = fileinfo.path();
	if(_plugin == NULL)
	{
		#ifndef NDEBUG
			{
				_plugin = new QPluginLoader(_applicationDir + "\\qcncodecsd4.dll");
			}
		#else
			{
				_plugin = new QPluginLoader(_applicationDir + "\\qcncodecs4.dll");
			}
		#endif
	}
	if(! _plugin->load())
	{
		QMessageBox::information(NULL,"error",_plugin->errorString (),QMessageBox::Ok);
	}
	else
	{
		ChineseTextCodec::SetChineseCodecPluginObject(_plugin->instance());
		QTextCodec::setCodecForLocale(QTextCodec::codecForName("GBK"));
		QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GBK"));
		QTextCodec::setCodecForTr(QTextCodec::codecForName("GBK"));
	}
	VrDataCore::DataManager::GetInstance().setApplicationDir(_applicationDir);
	VrDataCore::DataManager::GetInstance().configSceneContextFilePath();
	SetDllDirectory(reinterpret_cast<const wchar_t *>(_applicationDir.utf16()));
	if(!VrDataCore::WriteLogManager::GetInstance().haveSetFileDir())
		VrDataCore::WriteLogManager::GetInstance().setDefaultLogPath(_applicationDir);
}

bool ImplementActivex::openMap(const QString& mapname)
{
	closeMap();
	bool result = _activexView->openMap(mapname);
	afterOpenMap();
	return result;
}

void ImplementActivex::afterOpenMap()
{
	setScanMode(_currentScanMode);
}

bool ImplementActivex::closeMap()
{
	if(_activexView->haveOpenMap())
	{
		return _activexView->closeMap();
	}
	else
		return false;
}

void ImplementActivex::setScanMode(int mode)
{
	_currentScanMode = mode;
	_activexView->setScanMode(mode);
}

void ImplementActivex::setScanSpeed(int speed)
{
	_activexView->setScanSpeed(_currentScanMode,speed);
}

void ImplementActivex::setScanParameterAt(int scanmode,double offsetxy,double offsetxz,double distance,double x,double y,double z)
{
	float ey = distance*cos(osg::DegreesToRadians(offsetxy))*sin(osg::DegreesToRadians(offsetxz));
	float ex = distance*cos(osg::DegreesToRadians(offsetxy))*cos(osg::DegreesToRadians(offsetxz));
	float ez = distance*sin(osg::DegreesToRadians(offsetxy));
	osg::Vec3 upval = osg::Quat(osg::DegreesToRadians(offsetxy),osg::Vec3(0.0f,-1.0f,0.0f))*osg::Vec3(0.0f,0.0f,1.0f);
	osg::Vec3 eye = osg::Vec3(ex,ey,ez)+osg::Vec3(x,y,z);;
	osg::Vec3 up = osg::Quat(osg::DegreesToRadians(offsetxz),osg::Vec3(0.0f,0.0f,1.0f))*upval;
	osg::Vec3 center = osg::Vec3(x,y,z);
	_activexView->setScanParameterAt(scanmode,eye,center,up);
}

void ImplementActivex::setScanParameterAt_2(int scanmode,double eyex,double eyey,double eyez,double centerx,double centery,
	double centerz,double upx,double upy,double upz)
{
	osg::Vec3 eye = osg::Vec3(eyex,eyey,eyez);
	osg::Vec3 center = osg::Vec3(centerx,centery,centerz);
	osg::Vec3 up = osg::Vec3(upx,upy,upz);
	_activexView->setScanParameterAt(scanmode,eye,center,up);
}

bool ImplementActivex::followObject(const QString& id,double centeroffsetx,double centeroffsety,double centeroffsetz,int distance,int anglexy, int anglexz)
{
	return _activexView->followObject(id,centeroffsetx,centeroffsety,centeroffsetz,distance,anglexy,anglexz);
}

void ImplementActivex::setLookAt(const QString& id,int offsetxy,int offsetxz,int distance)
{
	if(_activexView->haveOpenMap())
	{
		_activexView->setLookAt(id,offsetxy,offsetxz,distance);
	}
}

void ImplementActivex::getLookAt(double& eyex,double& eyey,double& eyez,double& centerx,double& centery,
										double& centerz,double& upx,double& upy,double& upz,double& distance)
{
	if(_activexView->haveOpenMap())
	{
		float feyex,feyey,feyez,fcenterx,fcentery,fcenterz,fupx,fupy,fupz,fdistance;
		_activexView->getLookAt(feyex,feyey,feyez,fcenterx,fcentery,fcenterz,fupx,fupy,fupz,fdistance);
		eyex = feyex;
		eyey = feyey;
		eyez = feyez;
		centerx = fcenterx;
		centery = fcentery;
		centerz = fcenterz;
		upx = fupx;
		upy = fupy;
		upz = fupz;
		distance = fdistance;
	}
}

void ImplementActivex::updateObjectsMotion(ObjectEntitiesArray* entitiesarray)
{
	if(_activexView->haveOpenMap())
	{
		_activexView->updateObjectsMotion(entitiesarray);
	}
}

void ImplementActivex::createOrUpdateObjects_2(const QString& shipid,const QString& mmsi,const QString& imo,const QString& type,
		const QString& name,double lng,double lat,const QString& callsign,double beam,const QString& cargotype,
		const QString& country,double course,const QString& dest,double draught,const QString& eta,double heading,
		double lasttime,double left,double length,double rot,double speed,const QString& status,double trail)
{
	if(_activexView->haveOpenMap())
	{
		_activexView->createOrUpdateObjects_2(shipid,mmsi,imo,type,name,lng,lat,callsign,beam,cargotype,
			country,course,dest,draught,eta,heading,lasttime,left,length,rot,speed,status,trail);
	}
}

void ImplementActivex::createOrUpdateObjects_3(const QStringList& datalist)
{
	if(_activexView->haveOpenMap())
	{
		_activexView->createOrUpdateObjects_3(datalist);
	}
}

void ImplementActivex::setPropertyWindowParameter(int windowwidth,int windowheight,double namewidth,double valuewidth,
		int nametextsize,int valuetextsize,int nametextcolorr,int nametextcolorg,int nametextcolorb,int valuetextcolorr
		,int valuetextcolorg,int valuetextcolorb)
{
	_propertyWindowParameter._nameTextColor = osg::Vec3(nametextcolorr/255.0f,nametextcolorg/255.0f,nametextcolorb/255.0f);
	_propertyWindowParameter._nameTextSize = nametextsize;
	_propertyWindowParameter._nameWidth = namewidth;
	_propertyWindowParameter._valueTextColor = osg::Vec3(valuetextcolorr/255.0f,valuetextcolorg/255.0f,valuetextcolorb/255.0f);
	_propertyWindowParameter._valueTextSize = valuetextsize;
	_propertyWindowParameter._valueWidth = valuewidth;
	_propertyWindowParameter._windowsWidth = windowwidth;
	_propertyWindowParameter._windowsHeight = windowheight;
	_activexView->setPropertyWindowParameter(_propertyWindowParameter._windowsWidth,_propertyWindowParameter._windowsHeight,
		_propertyWindowParameter._nameWidth,_propertyWindowParameter._valueWidth,_propertyWindowParameter._nameTextSize
		,_propertyWindowParameter._valueTextSize,_propertyWindowParameter._nameTextColor,_propertyWindowParameter._valueTextColor);
	_propertyWindowParameter._setting = true;
}

//void ImplementActivex::updateProfessionProperty(ObjectEntities* entities)
//{
//	if(_activexView->haveOpenMap())
//	{		
//		_activexView->updateProfessionProperty(entities);
//	}
//}

bool ImplementActivex::deleteObject(const QString& id)
{
	return _activexView->deleteObject(id);
}

bool ImplementActivex::createAutoMoveObjectWithTrack(ObjectEntities* entities, PositionArray* p,DoubleArray* t,bool loop)
{
	return _activexView->createAutoMoveObjectWithTrack(entities,p,t,loop);
}

bool ImplementActivex::createAutoUniformMoveObjectWithTrack(ObjectEntities* entities, PositionArray* p,double speed,bool loop)
{
	return _activexView->createAutoUniformMoveObjectWithTrack(entities,p,speed,loop);
}

void ImplementActivex::showPropertyWidget(ObjectEntities* entities)
{
	if(_activexView->haveOpenMap())
	{
		if(!_propertyWindowParameter._setting)
		{
			_activexView->setPropertyWindowParameter(_propertyWindowParameter._windowsWidth,_propertyWindowParameter._windowsHeight,
			_propertyWindowParameter._nameWidth,_propertyWindowParameter._valueWidth,_propertyWindowParameter._nameTextSize
			,_propertyWindowParameter._valueTextSize,_propertyWindowParameter._nameTextColor,_propertyWindowParameter._valueTextColor);
			_propertyWindowParameter._setting = true;
		}
		_activexView->showPropertyWidget(entities);
	}
}

void ImplementActivex::moveCenterTo(double x,double y)
{
	_activexView->moveCenterTo(x,y);
}

void ImplementActivex::zoom(double ratio)
{
	_activexView->zoom(ratio);
}

void ImplementActivex::hidePropertyWidget()
{
	_activexView->hidePropertyWidget();
}

void ImplementActivex::setToolTip(const QString& text)
{
	if(_activexView->haveOpenMap())
	{
		_activexView->setToolTip(text);
	}
}

void ImplementActivex::setToolTipParameter(int textsize,int textr,int textg,int textb,int backgroundr,
		int backgroundg,int backgroundb,int backgrounda)
{
	if(_activexView->haveOpenMap())
	{
		_activexView->setToolTipParameter(textsize,textr,textg,textb,backgroundr,
			backgroundg,backgroundb,backgrounda);
	}
}

void ImplementActivex::markObject(const QString& ids,const QString& texts,int type,int r,int g,int b,int scal)
{
	if(_activexView->haveOpenMap())
	{
		_activexView->markObject(ids,texts,type,r,g,b,scal);
	}
}

void ImplementActivex::unMarkObject(const QString& ids)
{
	if(_activexView->haveOpenMap())
	{
		_activexView->unMarkObject(ids);
	}
}

void ImplementActivex::makeObjectColorBlink(const QString& ids,int totaltime,int intterval,int r,int g,int b,int a)
{
	if(_activexView->haveOpenMap())
	{
		_activexView->makeObjectColorBlink(ids,totaltime,intterval,r,g,b,a);
	}
}

void ImplementActivex::stopObjectColorBlink(const QString& ids)
{
	if(_activexView->haveOpenMap())
	{
		_activexView->stopObjectColorBlink(ids);
	}
}

void ImplementActivex::makeObjectBlink(const QString& ids,int totaltime,int intterval)
{
	if(_activexView->haveOpenMap())
	{
		_activexView->makeObjectBlink(ids,totaltime,intterval);
	}
}

void ImplementActivex::stopObjectBlink(const QString& ids)
{
	if(_activexView->haveOpenMap())
	{
		_activexView->stopObjectBlink(ids);
	}
}

void ImplementActivex::setCommondShapeParameter(int shapeType,int radious,int minh,int maxh,double minv,double maxv,int minr,int ming,int minb,
	int maxr,int maxg,int maxb,int a,bool autosize,bool canbeblock)
{
	_commonShapeParameter._setting = true;
	_commonShapeParameter._type = shapeType;
	_commonShapeParameter._minValue = minv;
	_commonShapeParameter._maxValue = maxv;
	_commonShapeParameter._minColor = osg::Vec4(minr/255.0f,ming/255.0f,minb/255.0f,a/255.0f);
	_commonShapeParameter._maxColor = osg::Vec4(maxr/255.0f,maxg/255.0f,maxb/255.0f,a/255.0f);
	_commonShapeParameter._autoSize = autosize;
	_commonShapeParameter._canBeBlock = canbeblock;
	_commonShapeParameter._minHeight = minh;
	_commonShapeParameter._maxHeight = maxh;
	_commonShapeParameter._radious = radious;
}

void ImplementActivex::defaultCommondShapeParameter()
{
	_commonShapeParameter._setting = true;
	_commonShapeParameter._type = 0;
	_commonShapeParameter._minValue = 0;
	_commonShapeParameter._maxValue = 0;
	_commonShapeParameter._minColor = osg::Vec4(0,1,0,1);
	_commonShapeParameter._maxColor = osg::Vec4(0,1,0,1);
	_commonShapeParameter._autoSize = true;
	_commonShapeParameter._canBeBlock = false;
	_commonShapeParameter._minHeight = -1;
	_commonShapeParameter._maxHeight = -1;
	_commonShapeParameter._radious = -1;
}

void ImplementActivex::updateCommondShape(const QString& ids,const QString& values)
{
	QStringList idlist = ids.split(',',QString::SkipEmptyParts);
	if(idlist.size()<1)
	{
		//log
		return;
	}
	if(!_commonShapeParameter._setting)
		defaultCommondShapeParameter();
	QStringList valuelist = values.split(',',QString::SkipEmptyParts);
	for(int i=0;i<idlist.size();++i)
	{
		float valuefloat = 0;
		if(valuelist.size()>i)
			valuefloat = valuelist.at(i).toFloat();
		osg::Vec4 color = mixColor(_commonShapeParameter._minColor,_commonShapeParameter._maxColor,
				_commonShapeParameter._minValue,_commonShapeParameter._maxValue,valuefloat);
		float totalvalue = _commonShapeParameter._maxValue - _commonShapeParameter._minValue;
		float heightpercent = 1.0f;
		if(totalvalue>0)
			heightpercent = valuefloat/totalvalue;
		float totalheight = _commonShapeParameter._maxHeight - _commonShapeParameter._minHeight;
		_activexView->updateCommondShape(idlist.at(i),_commonShapeParameter._type,color,_commonShapeParameter._radious,heightpercent,
		totalheight,_commonShapeParameter._autoSize,_commonShapeParameter._canBeBlock);
	}
}

void ImplementActivex::clearCommondShape()
{
	_activexView->clearCommondShape();
}

void ImplementActivex::addTabsInteractionWindow(const QString& title,int r,int g,int b)
{
	_activexView->addTabsInteractionWindow(title,osg::Vec3(r/255.0f,g/255.0f,b/255.0f));
}

void ImplementActivex::removeTabsInteractionWindow(const QString& title)
{
	_activexView->removeTabsInteractionWindow(title);
}

void ImplementActivex::addTextInteractionInformationWindow(const QString& text,const QString& title)
{
	_activexView->addTextInteractionInformationWindow(text,title);
}

osg::Vec4 ImplementActivex::mixColor(const osg::Vec4& start,const osg::Vec4& end,double min,double max,double current)
{
	osg::Vec4 color = start;
	if( (current>=min) && (current<=max))
	{
		float factor = (current-min)/(max-min) ;
		color = end*(1-factor) + start*factor ;
	}
	else
	{
		//log
	}
	return color;
}

void ImplementActivex::setObjectsValidStatus(const QString& ids,const QString& status)
{
	QStringList idlist = ids.split(",",QString::SkipEmptyParts);
	QStringList statuslist = status.split(",",QString::SkipEmptyParts);
	_activexView->setObjectsValidStatus(idlist,statuslist);
}

bool ImplementActivex::showObject(const QString& id,bool state)
{
	return _activexView->showObject(id,state);
}

bool ImplementActivex::showObjects(QVector<QString> ids,bool state)
{
	return _activexView->showObjects(ids,state);
}

bool ImplementActivex::showTarget(int type, int subtype,bool state)
{
	return _activexView->showTarget(type,subtype,state);
}

void ImplementActivex::setDefaultResourceDir(const QString& dir)
{
	VrDataCore::DataManager::GetInstance().setSourceLoadDirectory(dir);
}

void ImplementActivex::showRemarkLayer(const QString& remarkname)
{
	QStringList namelist = remarkname.split(",",QString::SkipEmptyParts);
	_activexView->showRemarkLayer(namelist);
}

void ImplementActivex::hideRemarkLayer(const QString& remarkname)
{
	QStringList namelist = remarkname.split(",",QString::SkipEmptyParts);
	_activexView->hideRemarkLayer(namelist);
}

void ImplementActivex::showArea(const QString& areaname)
{
	QStringList namelist = areaname.split(",",QString::SkipEmptyParts);
	_activexView->showArea(namelist);
}

void ImplementActivex::hideArea(const QString& areaname)
{
	QStringList namelist = areaname.split(",",QString::SkipEmptyParts);
	_activexView->hideArea(namelist);
}

void ImplementActivex::addToolBarButton(int buttonType)
{
	_activexView->addToolBarButton(buttonType);
}

void ImplementActivex::setToolBarActive(int type,bool active)
{
	_activexView->setToolBarActive(type,active);
}

void ImplementActivex::addRemarkedAt(const QString& remarklayername,const QString& text,double x,double y,double z)
{
	_activexView->addRemarkedAt(remarklayername,text,x,y,z);
}

void ImplementActivex::removeRemark(const QString& remarklayername,const QString& text)
{
	_activexView->removeRemark(remarklayername,text);
}

void ImplementActivex::addAdvancedToolBarButton(int type,const QString& buttonname,const QString& buttonicon,const QString& buttoniconeffect)
{
	_activexView->addAdvancedToolBarButton(type,buttonname,buttonicon,buttoniconeffect);
}

void ImplementActivex::playCameraAnimation(const QString& name)
{
	_activexView->playCameraAnimation(name);
}

QString ImplementActivex::getAllPlayCameraAnimationName()
{
	return _activexView->getAllPlayCameraAnimationName();
}

void ImplementActivex::showGuideMapWindow()
{
	_activexView->showGuideMapWindow();
}

void ImplementActivex::hideGuideMapWindow()
{
	_activexView->hideGuideMapWindow();
}